home *** CD-ROM | disk | FTP | other *** search
- #ifndef DCOSINEFFT_H
- #define DCOSINEFFT_H
- #pragma once
-
- /*
- * Double Precision Fast Cosine server
- *
- * Copyright (C) 1988, 1989.
- *
- * Dr. Thomas Keffer
- * Rogue Wave Associates
- * P.O. Box 85341
- * Seattle WA 98145-1341
- *
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and
- * without fee is hereby granted, provided that the
- * above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice
- * appear in supporting documentation.
- *
- * This software is provided "as is" without any
- * expressed or implied warranty.
- *
- *
- * @(#)DCosineFFT.h 2.1 8/18/89
- */
-
- #include "DoubleFFT.h"
-
- /* The transform of a real, even sequence is a cosine transform.
- The transform of a real, odd sequence is a sine transform.
-
- ************* E V E N S E Q U E N C E ****************
-
- A real "even" vector is one that is symmetric, i.e., V(j) == V(-j), or
- V(j) == V(2N-j) where 2N is the total length of the vector. Of the 2N
- points, only the N+1 points V(j), j =0,...,N need be given. Hence, N
- == V.length()-1. The upper half of V can be recovered from V(j) =
- V(2N-j),j=N+1,...,2N-1. This means that of the total 2N sequence, N-1
- values are repeated twice, and two [V(0) and V(N)] are unique, for a
- total of 2N points, of which only N+1 are actually stored.
-
- V(0), V(1), ... V(N), V(N+1), V(N+1), ... V(2N-1)
- ^ ^
- | | V(N-1), V(N-2), ... V(1) <---reflection
- +---------------+
- N+1 points
- stored
-
- The inverse fourier transform (IDFT) of a real even sequence is a
- cosine transform. The result is also a real even sequence. The
- transform is defined as follows. Assume (as above) that V(j),
- j=0,1,2,...,2N-1 is real and that V(j) == V(2N-j). Then
-
- 2N-1
- V(j) = sum C(n) exp(pi * n * j * I / N)
- n=0
- or
-
- N-1
- V(j) = a(0)/2 + sum a(n) cos(pi * j * n / N) + 0.5*(-1)**j * a(N)
- n=1
-
- where the a(n)'s are real and a(n) = 2C(n).
-
- It also follows that the forward fourier transform (DFT) of V(j) can
- be expressed as a cosine series:
- N-1
- a(n) = (2/N)*(V(0)/2 + sum V(j) cos(pi * j * n / N) + 0.5*(-1)**n * V(N))
- j=1
-
- The real part of C(n) is what is actually returned by cosine().
-
-
- ************* O D D S E Q U E N C E ****************
-
- A real "odd" vector is one that is anti-symmetric, i.e., V(j) ==
- -V(-j), or V(j) == -V(2N-j). As above, the vector V should be thought
- of as 2N points long, but, here, only the points V(j), j=1,...,N-1, a
- total of N-1 points (rather than N+1), need be given. This is because
- we know that V(0) and V(N) must always be zero for the sequence to be
- odd. Hence, N == length()+1. This means that of the total 2N
- sequence, N-1 values are repeated twice, and two are always zero, for
- a total of 2N points, of which only N-1 are actually stored.
-
- V(0), V(1), ... V(N-1), V(N), V(N+1), V(N+1), ... V(2N-1)
- ^ ^ ^ ^
- | | | | V(N-1), V(N-2), ... V(1) <---reflection
- | +----------+ |
- always -+ N-1 points +--always
- zero stored zero
-
- The sine transform is defined as:
-
- N-1
- V(j) = sum b(n) sin(pi * j * n / N)
- n=1
-
- and
- N-1
- b(n) = (2/N) * ( sum V(j) sin(pi * j * n / N).
- j=1
-
- The imaginary part of C(n) is what is actually returned by sine().
-
-
- ************* N O T E S ****************
-
- Due to an algorithmic limitation, the cosine and sine transforms are
- limited to sequences with N even. In other words, the length() of the
- vector V must be odd. Too bad!
-
- Speed Note: In general, one has the choice of using a cosine
- transform, or expanding the series out to the full series and using a
- regular complex FFT, saving only the lower half of the real part. The
- cosine transform is at its worst relative to the full complex fft for
- short series that are a power of 2 in length (empirically, series that
- are 32, 16, 8, etc. points long). In this case, you might want to
- consider using the complex transform. But for longer series, or
- series that are not a power of 2 long, you are better off using the
- cosine server. This also has the advantage of leaving yourself open
- to later optimizations. */
-
- class DoubleCosineServer : public DoubleFFTServer {
- unsigned server_N;
- DoubleVec sins;
- protected:
- void checkOdd(int);
- public:
- DoubleCosineServer();
- DoubleCosineServer(unsigned N);
- DoubleCosineServer(const DoubleCosineServer&);
-
- void operator=(const DoubleCosineServer&);
-
- unsigned order() {return server_N;}
- void setOrder(unsigned); // Set new server_N
-
- /*********** TRANSFORMS ***********/
- // Returns DFT of a real even sequence, which is an even sequence:
- DoubleVec cosine(const DoubleVec& v);
- // Returns DFT of a real odd sequence, which is an odd sequence:
- DoubleVec sine(const DoubleVec& v);
- };
-
- #endif
-